﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace ImageRenderControl
{
    // 矩形图形，支持旋转和缩放
    public class RectangleShape : Shape
    {
        public float TopLeftX { get; set; }
        public float TopLeftY { get; set; }
        public float BottomRightX { get; set; }
        public float BottomRightY { get; set; }
        public float Width => Math.Abs(BottomRightX - TopLeftX);
        public float Height => Math.Abs(BottomRightY - TopLeftY);
        public Pen Pen { get; set; }
        public float Rotation { get; private set; } = 0f;
        public float Scale { get; private set; } = 1f;

        // 添加图像坐标属性
        public PointF TopLeftImage { get; private set; }
        public PointF BottomRightImage { get; private set; }

        // 常量
        public const float RotationDelta = 1f;
        public const float ScaleFactorUp = 1.02f;
        public const float ScaleFactorDown = 0.98f;
        private const float HANDLE_SIZE = 8f;
        private const float MIN_SIZE = 10f;

        // 缓存变换矩阵
        private Matrix _rotationMatrix;
        private bool _matrixDirty = true;

        /// <summary>
        /// 仅使用Overlay坐标创建矩形
        /// </summary>
        public RectangleShape(float topLeftX, float topLeftY, float bottomRightX, float bottomRightY, Pen pen = null)
        {
            TopLeftX = topLeftX;
            TopLeftY = topLeftY;
            BottomRightX = bottomRightX;
            BottomRightY = bottomRightY;
            Pen = pen ?? new Pen(Color.Red, 2);

            // 初始化图像坐标为默认值，需要后续调用UpdateImageCoordinates方法设置正确值
            TopLeftImage = new PointF(0, 0);
            BottomRightImage = new PointF(0, 0);
        }

        /// <summary>
        /// 使用Overlay坐标和对应的图像坐标创建矩形
        /// </summary>
        public RectangleShape(float topLeftX, float topLeftY, float bottomRightX, float bottomRightY,
                             float topLeftImageX, float topLeftImageY, float bottomRightImageX, float bottomRightImageY,
                             Pen pen = null)
        {
            TopLeftX = topLeftX;
            TopLeftY = topLeftY;
            BottomRightX = bottomRightX;
            BottomRightY = bottomRightY;
            Pen = pen ?? new Pen(Color.Red, 2);

            // 初始化图像坐标
            TopLeftImage = new PointF(topLeftImageX, topLeftImageY);
            BottomRightImage = new PointF(bottomRightImageX, bottomRightImageY);
        }


        public Matrix RotationMatrix
        {
            get
            {
                if (_matrixDirty || _rotationMatrix == null)
                {
                    _rotationMatrix?.Dispose();
                    _rotationMatrix = new Matrix();
                    _rotationMatrix.Translate(TopLeftX, TopLeftY);
                    _rotationMatrix.Rotate(Rotation);
                    _rotationMatrix.Translate(-TopLeftX, -TopLeftY);
                    _matrixDirty = false;
                }
                return _rotationMatrix;
            }
        }

        public RectangleF Bounds => new RectangleF(TopLeftX, TopLeftY, Width, Height);

        /// <summary>
        /// 调整旋转角度
        /// </summary>
        public void AdjustRotation(float delta, Func<PointF, PointF> overlayToImageTransform)
        {
            Rotation += delta;
            _matrixDirty = true;

            // 更新图像坐标
            UpdateImageCoordinates(overlayToImageTransform);
        }

        /// <summary>
        /// 根据缩放因子调整矩形大小
        /// </summary>
        public void AdjustSize(float factor, Func<PointF, PointF> overlayToImageTransform)
        {
            // 获取中心点
            float centerX = TopLeftX + Width / 2;
            float centerY = TopLeftY + Height / 2;

            // 计算新宽高
            float newWidth = Width * factor;
            float newHeight = Height * factor;

            // 如果缩放后尺寸太小，则不处理
            if (newWidth < MIN_SIZE || newHeight < MIN_SIZE)
                return;

            // 调整坐标保持中心点不变
            TopLeftX = centerX - newWidth / 2;
            TopLeftY = centerY - newHeight / 2;
            BottomRightX = centerX + newWidth / 2;
            BottomRightY = centerY + newHeight / 2;

            Scale *= factor;
            _matrixDirty = true;

            // 更新图像坐标
            UpdateImageCoordinates(overlayToImageTransform);
        }

        /// <summary>
        /// 更新矩形的位置和大小
        /// </summary>
        public void UpdateFromResizing(float newX, float newY, float newWidth, float newHeight)
        {
            TopLeftX = newX;
            TopLeftY = newY;
            BottomRightX = newX + newWidth;
            BottomRightY = newY + newHeight;

            _matrixDirty = true;  // 标记矩阵需要重建
        }

        public override void Draw(Graphics g)
        {
            // 保存图形状态
            GraphicsState state = g.Save();

            try
            {
                g.MultiplyTransform(RotationMatrix);
                RectangleF bounds = Bounds;

                // 根据选中状态使用不同的画笔
                using (Pen drawPen = IsSelected ? new Pen(Color.Blue, Pen.Width) : (Pen)Pen.Clone())
                {
                    g.DrawRectangle(drawPen, bounds.X, bounds.Y, bounds.Width, bounds.Height);
                }
            }
            finally
            {
                // 恢复图形状态
                g.Restore(state);
            }

            // 如果被选中，绘制调整大小的控制点
            if (IsSelected)
            {
                DrawHandles(g);
            }
        }

        private void DrawHandles(Graphics g)
        {
            var handles = GetHandleCenters();
            using (Brush fillBrush = new SolidBrush(Color.Yellow))
            using (Pen borderPen = new Pen(Color.Black, 1))
            {
                foreach (var handle in handles.Values)
                {
                    RectangleF handleRect = new RectangleF(
                        handle.X - HANDLE_SIZE / 2,
                        handle.Y - HANDLE_SIZE / 2,
                        HANDLE_SIZE, HANDLE_SIZE);

                    g.FillRectangle(fillBrush, handleRect);
                    g.DrawRectangle(borderPen, handleRect.X, handleRect.Y, handleRect.Width, handleRect.Height);
                }
            }
        }

        public override bool Contains(Point p)
        {
            // 创建一个逆变换矩阵将点转换回非旋转坐标系
            using (Matrix inverseMatrix = RotationMatrix.Clone())
            {
                inverseMatrix.Invert();

                Point[] pts = new Point[] { p };
                inverseMatrix.TransformPoints(pts);

                return Bounds.Contains(pts[0]);
            }
        }

        public override void Move(float dx, float dy, Func<PointF, PointF> overlayToImageTransform)
        {
            if (IsSelected)
            {
                TopLeftX += dx;
                TopLeftY += dy;
                BottomRightX += dx;
                BottomRightY += dy;

                _matrixDirty = true;  // 标记矩阵需要重建

                // 更新图像坐标
                UpdateImageCoordinates(overlayToImageTransform);
            }
        }

        public enum ResizeHandle
        {
            TopLeft,
            TopCenter,
            TopRight,
            MiddleLeft,
            MiddleRight,
            BottomLeft,
            BottomCenter,
            BottomRight
        }

        /// <summary>
        /// 获取调整大小控制点的坐标，已应用旋转变换
        /// </summary>
        public Dictionary<ResizeHandle, PointF> GetHandleCenters()
        {
            var handles = new Dictionary<ResizeHandle, PointF>();
            RectangleF bounds = Bounds;

            // 计算8个控制点的原始位置
            PointF topLeft = new PointF(bounds.Left, bounds.Top);
            PointF topRight = new PointF(bounds.Right, bounds.Top);
            PointF bottomLeft = new PointF(bounds.Left, bounds.Bottom);
            PointF bottomRight = new PointF(bounds.Right, bounds.Bottom);
            PointF topCenter = new PointF(bounds.Left + bounds.Width / 2, bounds.Top);
            PointF bottomCenter = new PointF(bounds.Left + bounds.Width / 2, bounds.Bottom);
            PointF middleLeft = new PointF(bounds.Left, bounds.Top + bounds.Height / 2);
            PointF middleRight = new PointF(bounds.Right, bounds.Top + bounds.Height / 2);

            // 将所有点放入数组中一次性进行变换
            PointF[] points = new PointF[]
            {
                topLeft, topCenter, topRight,
                middleLeft, middleRight,
                bottomLeft, bottomCenter, bottomRight
            };

            RotationMatrix.TransformPoints(points);

            // 存储变换后的点
            handles[ResizeHandle.TopLeft] = points[0];
            handles[ResizeHandle.TopCenter] = points[1];
            handles[ResizeHandle.TopRight] = points[2];
            handles[ResizeHandle.MiddleLeft] = points[3];
            handles[ResizeHandle.MiddleRight] = points[4];
            handles[ResizeHandle.BottomLeft] = points[5];
            handles[ResizeHandle.BottomCenter] = points[6];
            handles[ResizeHandle.BottomRight] = points[7];

            return handles;
        }

        /// <summary>
        /// 判断点是否位于矩形边框上
        /// </summary>
        public bool IsPointOnBorder(Point p, float borderWidth = 5)
        {
            using (GraphicsPath path = new GraphicsPath())
            {
                path.AddRectangle(Bounds);

                // 应用旋转变换
                path.Transform(RotationMatrix);

                using (Pen testPen = new Pen(Color.Black, borderWidth))
                {
                    return path.IsOutlineVisible(p, testPen);
                }
            }
        }

        public void Dispose()
        {
            _rotationMatrix?.Dispose();
            Pen?.Dispose();
        }

        public override void UpdateImageCoordinates(Func<PointF, PointF> overlayToImageTransform)
        {
            if (overlayToImageTransform == null) return;

            // 转换左上角和右下角坐标
            TopLeftImage = overlayToImageTransform(new PointF(TopLeftX, TopLeftY));
            BottomRightImage = overlayToImageTransform(new PointF(BottomRightX, BottomRightY));
        }

        /// <summary>
        /// 获取图像坐标系中的所有关键点
        /// </summary>
        public PointF[] GetImageCoordinatePoints()
        {
            return new PointF[] { TopLeftImage, BottomRightImage };
        }

        /// <summary>
        /// 获取Overlay坐标系中的所有关键点
        /// </summary>
        public PointF[] GetOverlayCoordinatePoints()
        {
            return new PointF[] {
            new PointF(TopLeftX, TopLeftY),
            new PointF(BottomRightX, BottomRightY)
        };
        }
    }

}
